package com.buer.storage.common.aspect;


import com.buer.storage.business.domain.UserEntity;
import com.buer.storage.common.constant.Constant;
import com.buer.storage.common.eumn.RequestType;
import com.buer.storage.common.eumn.ResultEnum;
import com.buer.storage.common.handle.BaseException;
import com.buer.storage.common.holder.LoginUser;
import com.buer.storage.common.holder.LoginUserHolder;
import com.buer.storage.common.holder.UserCacheHolder;
import com.buer.storage.common.utils.RedisUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.EnumUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;


/**
 *
 * @ProjectName:
 * @Package:        com.buer.storage.common.aspect
 * @ClassName:      AuthAspect
 * @Description:    java类作用描述
 * @Author:         lds
 * @CreateDate:     2021/1/14 17:23
 * @UpdateUser:     更新者
 * @UpdateDate:     2021/1/14 17:23
 * @UpdateRemark:   更新内容
 * @Version:        1.0
 */
@Aspect
@Component
public class
AuthAspect {
    private static final Logger logger = LoggerFactory.getLogger(AuthAspect.class);

    @Autowired
    private HttpServletRequest request;



    @Pointcut("@annotation(com.buer.storage.common.annotation.Auth)")
    public void AuthPointCut() {
    }

    @Before("AuthPointCut()")
    public void around(JoinPoint point){
        String appTypeStr = request.getHeader(Constant.REQUEST_TYPE);
        logger.info("用户请求头：{}",appTypeStr);
        String tokenStr = request.getHeader(Constant.REQUEST_TOKEN);
        logger.info("用户Token：{}",appTypeStr);
        //step1 验证请求是否合法
        checkLegality(appTypeStr,tokenStr);
        //step2 验证redis中token是否存在
        UserCacheHolder cacheHolder=checkTokenAndGetUser(appTypeStr,tokenStr);
        //step3 穿插业务判断
        checkBusinessParams(cacheHolder.getUserDo());
        //step4 存入本地线程池
        LoginUserHolder.setLoginUserHolder(cacheHolder.getLoginUser());

    }

    private void checkLegality(String appTypeStr, String tokenStr) {
        if (StringUtils.isBlank(appTypeStr) || StringUtils.isBlank(tokenStr)) {
            logger.error("requestType或token不能为空，请求不合法");
            throw new BaseException(ResultEnum.ILLEGAL_ERROR);
        }
        if (!EnumUtils.isValidEnum(RequestType.class,appTypeStr)){
            throw new BaseException(ResultEnum.ILLEGAL_ERROR);
        }
    }


    private UserCacheHolder checkTokenAndGetUser(String appTypeStr, String tokenStr) {
        try {
            String key = appTypeStr + ":" + "token" + ":" + tokenStr;
            boolean hasToken = RedisUtil.hasKey(key);
            if (!hasToken) {
                logger.error("key：{}，在redis中不存在", key);
                throw new BaseException(ResultEnum.TOKEN_INVALID_ERROR);
            }
            LoginUser loginUser = (LoginUser)RedisUtil.get(key);
            if (loginUser==null) {
                logger.error("loginUser信息在redis中为空");
                throw new BaseException(ResultEnum.TOKEN_INVALID_ERROR);
            }
            String userKey = Constant.LOGINUSER + ":" + loginUser.getUserId();
            boolean hasUserId = RedisUtil.hasKey(userKey);
            if (!hasUserId) {
                logger.error("userKey：{}，在redis中不存在", userKey);
                throw new BaseException(ResultEnum.TOKEN_INVALID_ERROR);
            }
            UserEntity userDo = (UserEntity) RedisUtil.get(userKey);
            if (userDo == null) {
                logger.error("userDo信息在redis中为空");
                throw new BaseException(ResultEnum.TOKEN_INVALID_ERROR);
            }
            //更新redis失效时间
            RedisUtil.expire(key, Constant.REDIS_EXPIRE);

            UserCacheHolder cacheHolder=new UserCacheHolder();
            cacheHolder.setLoginUser(loginUser);
            cacheHolder.setUserDo(userDo);

            return cacheHolder;
        }catch (Exception e) {
            throw new BaseException(ResultEnum.REDIS_SERVER_ERROR);
        }

    }


    private void checkBusinessParams(UserEntity userDo) {
        if(Objects.equals(userDo.getStatus(),0)){
            logger.error("用户账户被禁用");
            throw new BaseException(ResultEnum.USER_FORBIDDEN);
        }
    }


    @After("AuthPointCut()")
    public void methodAfter(JoinPoint joinPoint){
        LoginUserHolder.clearLoginUserHolder();
    }

}
